(Derived from information published by Steve Tietze)
The Quake-C code files are used to define entity behavior, but they are also used to define the animation of models (.MDL files) used for monsters, players, and some objects.
The model informations are stored on special lines of code that all begin with a $. They cannot be placed inside a function definition. Some of this information is not even interpreted by the Quake-C compiler, but it's useful for the program modelgen that generates the models.
$modelname namename is the name of the model file defining the object. For instance:
$name armor
$cd dirSpecify the directory where your model file (.MDL) is located. For instance:
$cd /evil/models/armor.
$flags flag_valueThis field is not interpreted by Quake-C, but it's useful for the program modelgen that generates the models.
Possible values for the flag:
$origin x y zThis field is not interpreted by Quake-C, but it's useful for the program modelgen that generates the models.
$scale numberThis field is not interpreted by Quake-C, but it's useful for the program modelgen that generates the models.
$base objectThis field is not interpreted by Quake-C, but it's useful for the program modelgen that generates the models.
$skin skinfileThis field is not interpreted by Quake-C, but it's useful for the program modelgen that generates the models.
$frame frame1 frame2 ...This defines several animation frames of the object.
Most of these functions do nothing special, but some can be very complex (for instance, the functions that are called when the monster tries to see a player).
In order to use a Quake-C program, you must compile it into a file named PROGS.DAT. This is done by using the tool named qcc in the directory where all the Quake-C sources are. qcc is the Quake-C Compiler made by John Carmack of id software, it can be found on their ftp site, or on any mirror.
You must declare all the .QC source files in the file named PROGS.SRC. Note that all the .QC files will be compiled at the same time, and they be read in the same order as they are declared in PROGS.SRC.
Countrary to most language compilers, qcc behaves just as if all the .QC files were concatenated into a single big file. If you use an identifier (a name) that is already used somewhere in another .QC file, that will cause a conflict and compilation will fail.
So the best is to place your function declarations at the end of the first file, defs.h (so that they can be seen in all the code) but place your new .QC files (with function definitions) at the end of the list, so as to be sure that if a conflict happen, it will happen in your own files.
Note that qcc is not very user friendly, and does limited checks on the code. So you might wish to look for a better tool to compile your .QC code.
Note from John Carmack:
Error recovery during compilation is minimal. It will skip
to the next global definition, so you will never see more
than one error at a time in a given function. All compilation
aborts after ten error messages.
To use a custom PROGS.DAT that you just compiled, you only need to put it at the right place amoung the Quake game directory, and then Quake will find it automatically at startup.
The default PROGS.DAT can be found in the main pack file, pak0.pak in the directory id1. You could store your custom PROGS.DAT into that same directory id1.
Preferably, put PROGS.DAT in a special directory created for your own modified game, and that you will indicate to Quake with the option -game.
Here are some remarks by Adnan Zafar (zafar@hal-pc.org)
The compiler only catches syntax and other language-style errors. It will not warn you of things that generate run-time errors.. and definitely doesn't guarantee that things will work the way you want. It's been my experience that I have to compile and test something 6 or 8 times; the first few times it doesn't work at all, and the last few it doesn't work exactly right. [...] I just don't want you to think that all the code that compiles will have a good chance of working. In all likelihood, it won't.
Here are some more remarks from John Carmack:
Code execution is initiated by C code in quake from two main places:
the timed think routines for periodic control, and the touch function when
two objects impact each other.
Execution is also caused by a few uncommon events, like the addition of a new client to an existing server.
There is a runnaway counter that stops a program if 100000 statements are executed, assuming it is in an infinite loop.
It is acceptable to change the system set global variables. This is usually done to pose as another entity by changing self and calling a function.
The interpretation is fairly efficient, but it is still over an order of magnitude slower than compiled C code. All time consuming operations should be made into built in functions.
A profile counter is kept for each function, and incremented for each interpreted instruction inside that function. The "profile" console command in Quake will dump out the top 10 functions, then clear all the counters. The "profile all" command will dump sorted stats for every function that has been executed.